﻿// ------------------------------------------------------------------------------------------------
// <copyright file="CrmSolutionHelper.cs" company="Hiyoko">
//   Copyright (c) 2015 All Rights Reserved
// </copyright>
// <summary>
//   This helper class provide methods for retrieving and exporting Dynamics CRM solutions.
// </summary>
// -----------------------------------------------------------------------------------------------

using Hiyoko.SolutionsComparer.Model;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Collections.Generic;
using System.IO;

namespace Hiyoko.SolutionsComparer.Helper
{
    public static class CrmSolutionHelper
    {
        /// <summary>
        /// Retrieve the list of solutions.
        /// Source: http://msdn.microsoft.com/en-us/library/gg509050.aspx
        /// </summary>
        /// <param name="service">The CRM service</param>
        /// <returns>The list of solutions</returns>
        public static List<CrmSolution> RetrieveSolutions(IOrganizationService service)
        {
            var solutions = new List<CrmSolution>();

            var solutionsQuery = new QueryExpression
            {
                EntityName = "solution",
                ColumnSet = new ColumnSet(
                    new[] { "solutionid", "uniquename", "friendlyname", "version", "installedon", "publisherid", "description" }),
                Criteria = new FilterExpression()
            };

            solutionsQuery.Criteria.AddCondition("ismanaged", ConditionOperator.Equal, false);
            solutionsQuery.Criteria.AddCondition("isvisible", ConditionOperator.Equal, true);

            var solutionsResponse = service.RetrieveMultiple(solutionsQuery);

            if (solutionsResponse == null)
            {
                throw new ApplicationException(string.Format("An error occured while retrieving the solutions."));
            }

            foreach (var solutionResponse in solutionsResponse.Entities)
            {
                var solution = new CrmSolution
                {
                    SolutionId = solutionResponse.GetAttributeValue<Guid>("solutionid"),
                    UniqueName = solutionResponse.GetAttributeValue<String>("uniquename"),
                    FriendlyName = solutionResponse.GetAttributeValue<String>("friendlyname"),
                    Version = solutionResponse.GetAttributeValue<String>("version"),
                    InstalledOn = solutionResponse.GetAttributeValue<DateTime>("installedon"),
                    Publisher = solutionResponse.GetAttributeValue<EntityReference>("publisherid").Name,
                    Description = solutionResponse.GetAttributeValue<String>("description")
                };
                solutions.Add(solution);
            }

            return solutions;
        }

        /// <summary>
        /// Export the CRM solution.
        /// Source: http://msdn.microsoft.com/en-us/library/gg509050.aspx
        /// </summary>
        /// <param name="service">The CRM service</param>
        /// <param name="solutionName">The CRM solution name.</param>
        /// <param name="solutionFilePath">The solution file path</param>
        public static void ExportSolution(IOrganizationService service, string solutionName, string solutionFilePath)
        {
            if (string.IsNullOrEmpty(solutionName))
            {
                throw new ArgumentException(string.Format("The argument solutionName is null or empty."));
            }

            if (string.IsNullOrEmpty(solutionFilePath))
            {
                throw new ArgumentException(string.Format("The solutionFilePath solution is null or empty."));
            }

            var exportSolutionRequest = new ExportSolutionRequest
            {
                Managed = false,
                SolutionName = solutionName
            };
            var exportSolutionResponse = (ExportSolutionResponse)service.Execute(exportSolutionRequest);

            if (exportSolutionResponse == null)
            {
                throw new ApplicationException(string.Format("An error occured while retrieving the solution:\n{0} ", solutionName));
            }

            File.WriteAllBytes(solutionFilePath, exportSolutionResponse.ExportSolutionFile);
        }
    }
}
